home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / fs / fsSysCall.c < prev    next >
C/C++ Source or Header  |  1991-05-23  |  53KB  |  1,938 lines

  1. /* 
  2.  * fsSysCall.c --
  3.  *
  4.  *    These are the system call stubs that get called from the
  5.  *    system call trap handler.  These routines make sure that
  6.  *    their arguments are addressable and then call the workhorse
  7.  *    routines to do the actual work.
  8.  *
  9.  * Copyright 1987 Regents of the University of California
  10.  * All rights reserved.
  11.  * Permission to use, copy, modify, and distribute this
  12.  * software and its documentation for any purpose and without
  13.  * fee is hereby granted, provided that the above copyright
  14.  * notice appear in all copies.  The University of California
  15.  * makes no representations about the suitability of this
  16.  * software for any purpose.  It is provided "as is" without
  17.  * express or implied warranty.
  18.  */
  19.  
  20. #ifndef lint
  21. static char rcsid[] = "$Header: /sprite/src/kernel/fs/RCS/fsSysCall.c,v 9.9 91/05/21 11:32:56 mgbaker Exp $ SPRITE (Berkeley)";
  22. #endif not lint
  23.  
  24.  
  25. #include <sprite.h>
  26.  
  27. #include <fs.h>
  28. #include <fsutil.h>
  29. #include <fsutilTrace.h>
  30. #include <fsNameOps.h>
  31. #include <fsio.h>
  32. #include <fslcl.h>
  33. #include <fsdm.h>
  34. #include <vm.h>
  35. #include <proc.h>
  36.  
  37.  
  38. /*
  39.  *----------------------------------------------------------------------
  40.  *
  41.  * Fs_AttachDiskStub --
  42.  *
  43.  *    Stub for the Fs_AttachDisk system call.  This gets ahold of
  44.  *    the filename arguments, opens the disk to be attached, and
  45.  *    calls Fsdm_AttachDisk to do the work.
  46.  *
  47.  * Results:
  48.  *    SUCCESS, or an error code from finding junk on the disk.
  49.  *
  50.  * Side effects:
  51.  *    Call Fs_AttachDisk or Fs_DetachDisk.
  52.  *
  53.  *----------------------------------------------------------------------
  54.  */
  55.  
  56. ReturnStatus
  57. Fs_AttachDiskStub(userDeviceName, userLocalName, flags)
  58.     char *userDeviceName;/* Name of raw disk device file to attach */
  59.     char *userLocalName;/* Local directory name where disk is attached */
  60.     int flags;        /* FS_ATTACH_READ_ONLY, FS_DETATCH, FS_ATTACH_LOCAL */
  61. {
  62.     ReturnStatus status;
  63.     int useFlags;        /* Flags for the Fs_Open call */
  64.     Fs_Stream *streamPtr;    /* Stream from the Fs_Open call */
  65.     char *deviceName;        /* Kernel resident pathname storage */
  66.     char *localName;        /* Kernel resident pathname storage */
  67.     int    localNameLength;
  68.     int    deviceNameLength;
  69.  
  70.     if (userLocalName != (char *)NIL && userLocalName != (char *)0) {
  71.     localName = (char *)malloc(FS_MAX_PATH_NAME_LENGTH);
  72.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, userLocalName, localName,
  73.                &localNameLength) != SUCCESS) {
  74.         return(SYS_ARG_NOACCESS);
  75.     }
  76.     } else {
  77.     localName = (char *)NIL;
  78.     }
  79.     if (userDeviceName != (char *)NIL && userDeviceName != (char *)0) {
  80.     deviceName = (char *)malloc(FS_MAX_PATH_NAME_LENGTH);
  81.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, userDeviceName, deviceName,
  82.                &deviceNameLength) != SUCCESS) {
  83.         if (localName != (char *)NIL) {
  84.         free(localName);
  85.         }
  86.         return(SYS_ARG_NOACCESS);
  87.     }
  88.     } else {
  89.     deviceName = (char *)NIL;
  90.     }
  91.     if (flags & FS_DETACH) {
  92.     /*
  93.      * Flush data associated with the domain and remove the domain
  94.      * from the prefix table.
  95.      */
  96.     status = Fsdm_DetachDisk(localName);
  97.     } else {
  98.     /*
  99.      * Attach a local domain into the prefix table.
  100.      */
  101.     if (deviceName == (char *)NIL ||
  102.         localName == (char *)NIL) {
  103.         status = FS_INVALID_ARG;
  104.     } else {
  105.         if (flags & FS_ATTACH_READ_ONLY) {
  106.         useFlags = FS_READ;
  107.         } else {
  108.         useFlags = FS_READ|FS_WRITE;
  109.         }
  110.         status = Fs_Open(deviceName, useFlags, FS_DEVICE, 0, &streamPtr);
  111.         if (status == SUCCESS) {
  112.         status = Fsdm_AttachDiskByHandle(streamPtr->ioHandlePtr, 
  113.                          localName, flags);
  114.         }
  115.     }
  116.     }
  117.     if (deviceName != (char *)NIL) {
  118.     free(deviceName);
  119.     }
  120.     if (localName != (char *)NIL) {
  121.     free(localName);
  122.     }
  123.     return(status);
  124. }
  125.  
  126. /*
  127.  *----------------------------------------------------------------------
  128.  *
  129.  * Fs_OpenStub --
  130.  *
  131.  *      This is the stub for the Fs_Open system call.  This routine makes
  132.  *    its arguments accessible, then sets up a Stream ID for the Fs_Stream
  133.  *      object returned by (the internal) Fs_Open.  Stream Id's get
  134.  *      passed to read and write calls and identify the stream to the
  135.  *      system.  If FS_CREATE is one of the usage flags then the third
  136.  *      argument, permissions, specifies the base permissions for the
  137.  *      newly created file.
  138.  *
  139.  * Results:
  140.  *    An error code or SUCCESS if successful.
  141.  *
  142.  * Side effects:
  143.  *    The last argument is an out parameter and gets filled in with
  144.  *    the stream id.  
  145.  *
  146.  *----------------------------------------------------------------------
  147.  */
  148.  
  149. ReturnStatus
  150. Fs_OpenStub(pathName, usageFlags, permissions, streamIDPtr)
  151.     char *pathName;        /* The name of the file to open */
  152.     int usageFlags;        /* FS_READ, FS_WRITE, FS_CREATE, FS_TRUNC */
  153.     int permissions;        /* Permission mask to use on creation */
  154.     int *streamIDPtr;        /* This is the user's handle on the open
  155.                  * file used in later filesystem requests */
  156. {
  157.     int             streamID;
  158.     Fs_Stream         *streamPtr;
  159.     ReturnStatus     status;
  160.     int            pathNameLength;
  161.     char        newName[FS_MAX_PATH_NAME_LENGTH];
  162.  
  163.     FSUTIL_TRACE(FSUTIL_TRACE_OPEN);
  164.  
  165.     /*
  166.      * Copy the name in from user space to the kernel stack.
  167.      */
  168.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, pathName, newName,
  169.                &pathNameLength) != SUCCESS) {
  170.     return(SYS_ARG_NOACCESS);
  171.     }
  172.     if (pathNameLength == FS_MAX_PATH_NAME_LENGTH) {
  173.     return(FS_INVALID_ARG);
  174.     }
  175.  
  176.     /*
  177.      * Open the file and get a stream descriptor for it.
  178.      */
  179.     usageFlags &= ~FS_KERNEL_FLAGS;
  180.     usageFlags |= (FS_USER | FS_FOLLOW);
  181.     if (fsutil_Tracing) {
  182.     usageFlags |= FSUTIL_TRACE_FLAG;
  183.     }
  184.  
  185.     status = Fs_Open(newName, usageFlags, FS_FILE,
  186.              permissions & 0777, &streamPtr);
  187.     
  188.     FSUTIL_TRACE_NAME(FSUTIL_TRACE_OPEN_DONE_2, pathName);
  189.  
  190.     if (status != SUCCESS) {
  191.     return(status);
  192.     }
  193.  
  194.     /*
  195.      * Save a pointer to the descriptor in a list kept in the proc table.
  196.      * Its index in the list is the "Stream ID".
  197.      */
  198.  
  199.     status = Fs_GetStreamID(streamPtr, &streamID);
  200.     if (status != SUCCESS) {
  201.     (void) Fs_Close(streamPtr);
  202.     return(status);
  203.     }
  204.  
  205.     if (Vm_CopyOut(sizeof(int), (Address) &streamID, 
  206.            (Address) streamIDPtr) == SUCCESS) {
  207.     FSUTIL_TRACE(FSUTIL_TRACE_OPEN_DONE_3);
  208.     return(SUCCESS);
  209.     } 
  210.     status = SYS_ARG_NOACCESS;
  211.     (void) Fs_UserClose(streamID);    /* This clears the streamID, too */
  212.     return(status);
  213. }
  214.  
  215.  
  216. /*
  217.  *----------------------------------------------------------------------
  218.  *
  219.  * Fs_UserClose --
  220.  *
  221.  *    System call to release a stream Id.  Calls then internal Fs_Close
  222.  *    routine.
  223.  *
  224.  * Results:
  225.  *    An return status.
  226.  *
  227.  * Side effects:
  228.  *    The streamID becomes invalid (until it gets reassigned by
  229.  *    another Fs_Open call).
  230.  *
  231.  *----------------------------------------------------------------------
  232.  */
  233.  
  234. ReturnStatus
  235. Fs_UserClose(streamID)
  236.     int streamID;
  237. {
  238.     ReturnStatus    status;
  239.     Fs_Stream         *streamPtr;    /* Stream pointer from the process's
  240.                       * list of open streams */
  241.     Proc_ControlBlock    *procPtr;    /* This process's control block */
  242.     
  243.     /*
  244.      * Map from the streamID to a streamPtr.
  245.      */
  246.  
  247.     procPtr = Proc_GetEffectiveProc();
  248.     status = Fs_GetStreamPtr(procPtr, streamID, &streamPtr);
  249.     if (status != SUCCESS) {
  250.     /*
  251.      * Fudge the return status.  A close() can only return EBADF or
  252.      * EINTR, so return something that maps to EBADF even if it
  253.      * doesn't make sense here.  Sprite system calls are going
  254.      * away soon anyway.
  255.      */
  256.     if (status != GEN_ENOENT) {
  257.         return(FS_NEW_ID_TOO_BIG);
  258.     }
  259.     return(status);
  260.     }
  261.  
  262.     /*
  263.      * Look after any shared memory associated with the file.
  264.      */
  265.     if (procPtr->vmPtr->sharedSegs != (List_Links *)NIL) {
  266.     Vm_CleanupSharedFile(procPtr,streamPtr);
  267.     }
  268.  
  269.     /*
  270.      * Clear the user-level streamID and then close the underlying stream.
  271.      */
  272.  
  273.     Fs_ClearStreamID(streamID, procPtr);
  274.     status = Fs_Close(streamPtr);
  275.  
  276.     return(status);
  277. }
  278.  
  279.  
  280. /*
  281.  *----------------------------------------------------------------------
  282.  *
  283.  * Fs_ReadStub --
  284.  *
  285.  *      The stub for the Fs_Read system call.  Calls Fs_UserRead to do the
  286.  *    work, then copies out the argument to the user's address space.
  287.  *
  288.  * Results:
  289.  *    An return status.
  290.  *
  291.  * Side effects:
  292.  *    The amountReadPtr is updated to reflect the amount actually read.
  293.  *
  294.  *----------------------------------------------------------------------
  295.  */
  296.  
  297. ReturnStatus
  298. Fs_ReadStub(streamID, amountRead, buffer, amountReadPtr)
  299.     int        streamID;    /* The user's index into its open file list */
  300.     int        amountRead;    /* The amount of bytes to read */
  301.     Address    buffer;        /* The storage place for the read */
  302.     int        *amountReadPtr;    /* The amount of bytes actually read */
  303. {
  304.     register ReturnStatus    status;
  305.     Fs_Stream        *streamPtr;    /* The stream to read from */
  306.     Proc_ControlBlock     *procPtr;    /* This process's control block */
  307.  
  308.     /*
  309.      * (Begin inlined called to Fs_UserRead.)
  310.      */
  311.     /*
  312.      * Map from stream ID to file pointer and do the read.
  313.      * If the process is not remote, Fs_Read takes care of making
  314.      * the read buffer accessible.
  315.      */
  316.  
  317.     procPtr = Proc_GetEffectiveProc();
  318.     status = Fs_GetStreamPtr(procPtr, streamID, &streamPtr);
  319.     if (status == SUCCESS) {
  320.     status = Fs_Read(streamPtr, buffer, streamPtr->offset, &amountRead);
  321.     } else {
  322.     amountRead = 0;
  323.     }
  324.     /*
  325.      * (End Fs_UserRead.)
  326.      */
  327.  
  328.     if (Vm_CopyOut(sizeof(int), (Address) &amountRead, 
  329.            (Address) amountReadPtr) != SUCCESS) {
  330.     status = SYS_ARG_NOACCESS;
  331.     }
  332.     return(status);
  333. }
  334.  
  335.  
  336. /*
  337.  *----------------------------------------------------------------------
  338.  *
  339.  * Fs_UserRead --
  340.  *
  341.  *      The Fs_Read system call.  Read from the file indicated by the
  342.  *      stream id into the buffer.  bufSize indicates how much
  343.  *      data to read, and amountReadPtr is an output parameter that
  344.  *      indicates how much data was read.  A length of zero means
  345.  *      end-of-file.
  346.  *
  347.  * Results:
  348.  *    A return status.
  349.  *
  350.  * Side effects:
  351.  *    The amountReadPtr is updated to reflect the amount actually read.
  352.  *
  353.  *----------------------------------------------------------------------
  354.  */
  355.  
  356. ReturnStatus
  357. Fs_UserRead(streamID, amountRead, buffer, amountReadPtr)
  358.     int        streamID;    /* The user's index into its open file list */
  359.     int        amountRead;    /* The amount of bytes to read */
  360.     Address    buffer;        /* The storage place for the read */
  361.     int        *amountReadPtr;    /* The amount of bytes actually read */
  362. {
  363.     register ReturnStatus    status;
  364.     Fs_Stream        *streamPtr;    /* The stream to read from */
  365.     Proc_ControlBlock     *procPtr;    /* This process's control block */
  366.  
  367.     /*
  368.      * Map from stream ID to file pointer and do the read.
  369.      * If the process is not remote, Fs_Read takes care of making
  370.      * the read buffer accessible.
  371.      */
  372.  
  373.     procPtr = Proc_GetEffectiveProc();
  374.     status = Fs_GetStreamPtr(procPtr, streamID, &streamPtr);
  375.     if (status == SUCCESS) {
  376.     *amountReadPtr = amountRead;
  377.     status = Fs_Read(streamPtr, buffer, streamPtr->offset, amountReadPtr);
  378.     } else {
  379.     *amountReadPtr = 0;
  380.     }
  381.     return(status);
  382. }
  383.  
  384. /*
  385.  *----------------------------------------------------------------------
  386.  *
  387.  * Fs_ReadVectorStub --
  388.  *
  389.  *      The stub for the Fs_ReadVector system call.  Calls Fs_UserReadVector 
  390.  *    to do the work, then copies out the argument to the user's address 
  391.  *    space.
  392.  *
  393.  * Results:
  394.  *    An return status.
  395.  *
  396.  * Side effects:
  397.  *    The amountReadPtr is updated to reflect the amount actually read.
  398.  *
  399.  *----------------------------------------------------------------------
  400.  */
  401.  
  402. ReturnStatus
  403. Fs_ReadVectorStub(streamID, numVectors, userVectorArray, amountReadPtr)
  404.     int        streamID;    /* The user's index into its open file list. */
  405.     int        numVectors;    /* The # of vectors in userVectorArray. */
  406.     Fs_IOVector    userVectorArray[];    
  407.                 /* The vectors defining where and how much to
  408.                  * read. */
  409.     int        *amountReadPtr;    /* The amount of bytes actually read */
  410. {
  411.     ReturnStatus status;
  412.     int        amountRead;
  413.     Fs_IOVector *vectorPtr;
  414.  
  415.     if (numVectors < 0) {
  416.     return(SYS_INVALID_ARG);
  417.     }
  418.  
  419.     /*
  420.      * Copy the I/O vector into kernel space. The buffer addresses in each
  421.      * vector will be made accessible by the Fs_Read routine.
  422.      */
  423.     vectorPtr = (Fs_IOVector *) malloc(numVectors * sizeof(Fs_IOVector));
  424.     if (Vm_CopyIn(numVectors * sizeof(Fs_IOVector), 
  425.            (Address) userVectorArray,
  426.            (Address) vectorPtr) != SUCCESS) {
  427.     free((Address) vectorPtr);
  428.     return(SYS_ARG_NOACCESS);
  429.     }
  430.  
  431.     status = Fs_UserReadVector(streamID, numVectors, vectorPtr, &amountRead);
  432.  
  433.     free((Address) vectorPtr);
  434.     if (Vm_CopyOut(sizeof(int), (Address) &amountRead, 
  435.            (Address) amountReadPtr) != SUCCESS) {
  436.     status = SYS_ARG_NOACCESS;
  437.     }
  438.     return(status);
  439. }
  440.  
  441.  
  442. /*
  443.  *----------------------------------------------------------------------
  444.  *
  445.  * Fs_UserReadVector --
  446.  *
  447.  *      The Fs_ReadVector system call.  Read from the file indicated by
  448.  *      the stream ID into the buffer.  Each I/O vector contains a value
  449.  *      to indicate how much data to read. *AmountReadPtr contains the
  450.  *      total number of bytes read into the vector buffers.
  451.  *      *amountReadPtr will be smaller that the sum of the bufSize fields
  452.  *      in the vector array if an error occurs or an end-of-file is
  453.  *      reached.  A length of zero in *amountReadPtr means an end-of-file
  454.  *      occurred on the first buffer in the vector.
  455.  *
  456.  * Results:
  457.  *    A return status.
  458.  *
  459.  * Side effects:
  460.  *    The *amountReadPtr is updated to reflect the amount actually read.
  461.  *
  462.  *----------------------------------------------------------------------
  463.  */
  464.  
  465. ReturnStatus
  466. Fs_UserReadVector(streamID, numVectors, vectorPtr, amountReadPtr)
  467.     int        streamID;    /* The user's index into its open file list */
  468.     register int numVectors;    /* The # of vectors in vectorArray */
  469.     register Fs_IOVector *vectorPtr;    
  470.                 /* The vectors defining where and how much to 
  471.                  * read. */
  472.     int        *amountReadPtr;    /* Total # of bytes read. */
  473. {
  474.     ReturnStatus    status;
  475.     Fs_Stream        *streamPtr;    /* The stream to read from */
  476.     Proc_ControlBlock     *procPtr;    /* This process's control block */
  477.     register int    sum = 0;    /* Total # of bytes read. */
  478.     register int    i;
  479.  
  480.     /*
  481.      * Map from stream ID to file pointer and do the read.
  482.      * If the process is not remote, Fs_Read takes care of making
  483.      * the read buffer accessible.
  484.      */
  485.  
  486.     procPtr = Proc_GetEffectiveProc();
  487.     status = Fs_GetStreamPtr(procPtr, streamID, &streamPtr);
  488.  
  489.     if (status == SUCCESS) {
  490.     /*
  491.      * Doing a Fs_Read for each vector buffer is probably not the
  492.      * most efficiennt way to do this, but it is simple.
  493.      */
  494.     for (i= 0; i < numVectors; i++, vectorPtr++) {
  495.  
  496.         status = Fs_Read(streamPtr, vectorPtr->buffer, streamPtr->offset, 
  497.                 &(vectorPtr->bufSize));
  498.         /*
  499.          * Check to see if the read failed or we got an end-of-file.
  500.          */
  501.         if ((status != SUCCESS) || (vectorPtr->bufSize == 0)) {
  502.         break;
  503.         }
  504.         sum += vectorPtr->bufSize;
  505.     }
  506.     }
  507.     *amountReadPtr = sum;
  508.     return(status);
  509. }
  510.  
  511.  
  512. /*
  513.  *----------------------------------------------------------------------
  514.  *
  515.  * Fs_WriteStub --
  516.  *
  517.  *    The Fs_Write system call stub.  Calls Fs_UserWrite to do the
  518.  *    work, then copies out the amount written to the user's address space.
  519.  *
  520.  * Results:
  521.  *    A return status.
  522.  *
  523.  * Side effects:
  524.  *    The writeLengthPtr is updated to reflect the amount actually written.
  525.  *
  526.  *----------------------------------------------------------------------
  527.  */
  528.  
  529. ReturnStatus
  530. Fs_WriteStub(streamID, writeLength, buffer, writeLengthPtr)
  531.     int streamID;
  532.     int writeLength;
  533.     Address buffer;
  534.     int *writeLengthPtr;
  535. {
  536.     register ReturnStatus status;
  537.     Fs_Stream    *streamPtr;    /* The stream to write to */
  538.     Proc_ControlBlock *procPtr;    /* This process's control block */
  539.  
  540.     /*
  541.      * (Begin inlined Fs_UserWrite.)
  542.      */
  543.     /*
  544.      * Map from stream ID to streamPtr.  If the process is not remote,
  545.      * Fs_Write takes care of making the user's buffer accessible.
  546.      */
  547.     procPtr = Proc_GetEffectiveProc();
  548.     status = Fs_GetStreamPtr(procPtr, streamID, &streamPtr);
  549.     if (status == SUCCESS) {
  550.     status = Fs_Write(streamPtr, buffer, streamPtr->offset, &writeLength);
  551.     } else {
  552.     writeLength = 0;
  553.     }
  554.     /*
  555.      * (End inlined Fs_UserWrite.)
  556.      */
  557.     if (Vm_CopyOut(sizeof(int), (Address) &writeLength, 
  558.            (Address) writeLengthPtr) != SUCCESS) {
  559.     status = SYS_ARG_NOACCESS;
  560.     }
  561.     return(status);
  562. }
  563.  
  564.  
  565. /*
  566.  *----------------------------------------------------------------------
  567.  *
  568.  * Fs_UserWrite --
  569.  *
  570.  *    The user interface to Fs_Write.  Write writeLength characters from
  571.  *    buffer to the file identified by streamID.  *writeLengthPtr
  572.  *    is updated to reflect how much was actually written.
  573.  *
  574.  * Results:
  575.  *    A return status. 
  576.  *
  577.  * Side effects:
  578.  *    The writeLengthPtr is updated to reflect the amount actually written.
  579.  *
  580.  *----------------------------------------------------------------------
  581.  */
  582.  
  583. ReturnStatus
  584. Fs_UserWrite(streamID, writeLength, buffer, writeLengthPtr)
  585.     int streamID;
  586.     int writeLength;
  587.     Address buffer;
  588.     int *writeLengthPtr;
  589. {
  590.     ReturnStatus status;
  591.     Fs_Stream    *streamPtr;    /* The stream to write to */
  592.     Proc_ControlBlock *procPtr;    /* This process's control block */
  593.  
  594.     /*
  595.      * Map from stream ID to streamPtr.  If the process is not remote,
  596.      * Fs_Write takes care of making the user's buffer accessible.
  597.      */
  598.     procPtr = Proc_GetEffectiveProc();
  599.     status = Fs_GetStreamPtr(procPtr, streamID, &streamPtr);
  600.     if (status == SUCCESS) {
  601.     *writeLengthPtr = writeLength;
  602.     status = Fs_Write(streamPtr, buffer, streamPtr->offset, writeLengthPtr);
  603.     } else {
  604.     *writeLengthPtr = 0;
  605.     }
  606.     return(status);
  607. }
  608.  
  609. /*
  610.  *----------------------------------------------------------------------
  611.  *
  612.  * Fs_WriteVectorStub --
  613.  *
  614.  *      The stub for the Fs_WriteVector system call.  Calls Fs_UserWriteVector 
  615.  *    to do the work, then copies out the argument to the user's address 
  616.  *    space.
  617.  *
  618.  * Results:
  619.  *    An return status.
  620.  *
  621.  * Side effects:
  622.  *    The *amountWrittenPtr is updated to reflect the amount actually read.
  623.  *
  624.  *----------------------------------------------------------------------
  625.  */
  626.  
  627. ReturnStatus
  628. Fs_WriteVectorStub(streamID, numVectors, userVectorArray, amountWrittenPtr)
  629.     int        streamID;    /* The user's index into its open file list. */
  630.     int        numVectors;    /* The # of vectors in userVectorArray. */
  631.     Fs_IOVector    userVectorArray[];    
  632.                 /* The vectors defining where and how much to
  633.                  * write. */
  634.     int    *amountWrittenPtr;    /* The amount of bytes actually written. */
  635. {
  636.     ReturnStatus status;
  637.     int        amountWritten;
  638.     Fs_IOVector *vectorPtr;
  639.  
  640.     if (numVectors < 0) {
  641.     return(SYS_INVALID_ARG);
  642.     }
  643.  
  644.     /*
  645.      * Copy the I/O vector into kernel space. The buffer addresses in each
  646.      * vector will be made accessible by the Fs_Write routine.
  647.      */
  648.     vectorPtr = (Fs_IOVector *) malloc(numVectors * sizeof(Fs_IOVector));
  649.     if (Vm_CopyIn(numVectors * sizeof(Fs_IOVector), 
  650.            (Address) userVectorArray,
  651.            (Address) vectorPtr) != SUCCESS) {
  652.     free((Address) vectorPtr);
  653.     return(SYS_ARG_NOACCESS);
  654.     }
  655.  
  656.     status = Fs_UserWriteVector(streamID, numVectors, vectorPtr, 
  657.             &amountWritten);
  658.  
  659.     free((Address) vectorPtr);
  660.     if (Vm_CopyOut(sizeof(int), (Address) &amountWritten, 
  661.            (Address) amountWrittenPtr) != SUCCESS) {
  662.     status = SYS_ARG_NOACCESS;
  663.     }
  664.     return(status);
  665. }
  666.  
  667.  
  668. /*
  669.  *----------------------------------------------------------------------
  670.  *
  671.  * Fs_UserWriteVector --
  672.  *
  673.  *      The Fs_WriteVector system call.  Write from the file indicated by
  674.  *      the stream ID into the buffer.  Each I/O vector contains a value
  675.  *      to indicate how much data to write. *AmountWrittenPtr contains the
  676.  *      total number of bytes written from the vector buffers.
  677.  *
  678.  * Results:
  679.  *    A return status.
  680.  *
  681.  * Side effects:
  682.  *    The *amountWrittenPtr is updated to reflect the amount 
  683.  *    actually written.
  684.  *
  685.  *----------------------------------------------------------------------
  686.  */
  687.  
  688. ReturnStatus
  689. Fs_UserWriteVector(streamID, numVectors, vectorPtr, amountWrittenPtr)
  690.     int        streamID;    /* The user's index into its open file list */
  691.     register int numVectors;    /* The # of vectors in vectorArray */
  692.     register Fs_IOVector *vectorPtr;    
  693.                 /* The vectors defining where and how much to 
  694.                  * write. */
  695.     int        *amountWrittenPtr;    /* Total # of bytes written. */
  696. {
  697.     ReturnStatus    status;
  698.     Fs_Stream        *streamPtr;    /* The stream to write to. */
  699.     Proc_ControlBlock     *procPtr;    /* This process's control block. */
  700.     register int    sum = 0;    /* Total # of bytes written. */
  701.     register int    i;
  702.  
  703.     /*
  704.      * Map from stream ID to file pointer and do the write.
  705.      * If the process is not remote, Fs_Write takes care of making
  706.      * the write buffer accessible.
  707.      */
  708.  
  709.     procPtr = Proc_GetEffectiveProc();
  710.     status = Fs_GetStreamPtr(procPtr, streamID, &streamPtr);
  711.  
  712.     if (status == SUCCESS) {
  713.     /*
  714.      * Doing a Fs_Write for each vector buffer is probably not the
  715.      * most efficiennt way to do this, but it is simple.
  716.      */
  717.     for (i= 0; i < numVectors; i++, vectorPtr++) {
  718.  
  719.         status = Fs_Write(streamPtr, vectorPtr->buffer, streamPtr->offset, 
  720.                 &(vectorPtr->bufSize));
  721.         /*
  722.          * Check to see if the write failed or we got an end-of-file.
  723.          */
  724.         if ((status != SUCCESS) || (vectorPtr->bufSize == 0)) {
  725.         break;
  726.         }
  727.         sum += vectorPtr->bufSize;
  728.     }
  729.     }
  730.     *amountWrittenPtr = sum;
  731.     return(status);
  732. }
  733.  
  734. /*
  735.  *----------------------------------------------------------------------
  736.  *
  737.  * Fs_CommandStub --
  738.  *
  739.  *    Stub for the Fs_Command system call.  This copies in a buffer
  740.  *    containing arguments for the particular command, and copies
  741.  *    out whatever Fs_Command leaves in the buffer after its done.
  742.  *
  743.  * Results:
  744.  *    A return code.
  745.  *
  746.  * Side effects:
  747.  *    Call Fs_Command
  748.  *
  749.  *----------------------------------------------------------------------
  750.  */
  751.  
  752. ReturnStatus
  753. Fs_CommandStub(command, bufSize, buffer)
  754.     int command;    /* Defined in user include "test.h" */
  755.     int bufSize;    /* Size in bytes of buffer */
  756.     Address buffer;    /* In/Out - Command specific data */
  757. {
  758.     ReturnStatus status;
  759.     Address localBuffer;
  760.  
  761.     if (bufSize > 0) {
  762.     localBuffer = (Address)malloc(bufSize);
  763.     status = Vm_CopyIn(bufSize, buffer, localBuffer);
  764.     if (status != SUCCESS) {
  765.         return(status);
  766.     }
  767.     } else {
  768.     localBuffer = (Address)NIL;
  769.     }
  770.  
  771.     status = Fs_Command(command, bufSize, localBuffer);
  772.  
  773.     if (localBuffer != (Address)NIL) {
  774.     if (status == SUCCESS) {
  775.         status = Vm_CopyOut(bufSize, localBuffer, buffer);
  776.     }
  777.     free(localBuffer);
  778.     }
  779.     return(status);
  780. }
  781.  
  782. /*
  783.  *----------------------------------------------------------------------
  784.  *
  785.  * Fs_MakeDeviceStub --
  786.  *
  787.  *    The Fs_MakeDevice system call stub.
  788.  *
  789.  * Results:
  790.  *    Those of Fs_MakeDevice.
  791.  *
  792.  * Side effects:
  793.  *    None.
  794.  *
  795.  *----------------------------------------------------------------------
  796.  */
  797.  
  798. ReturnStatus
  799. Fs_MakeDeviceStub(pathName, devicePtr, permissions)
  800.     char *pathName;        /* Device file to create */
  801.     Fs_Device *devicePtr;    /* Specifies the device file attributes */
  802.     int permissions;        /* Permissions on the special file */
  803. {
  804.     Fs_Device             device;
  805.     int                pathNameLength;
  806.     char            newName[FS_MAX_PATH_NAME_LENGTH];
  807.  
  808.     /*
  809.      * Copy the device name in from user space onto the kernel stack.
  810.      */
  811.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, pathName, newName,
  812.                &pathNameLength) != SUCCESS) {
  813.     return(SYS_ARG_NOACCESS);
  814.     }
  815.     if (pathNameLength == FS_MAX_PATH_NAME_LENGTH) {
  816.     return(FS_INVALID_ARG);
  817.     }
  818.     if (Vm_CopyIn(sizeof(Fs_Device), (Address)devicePtr, 
  819.           (Address)&device) != SUCCESS) {
  820.     return(SYS_ARG_NOACCESS);
  821.     }
  822.  
  823.     return(Fs_MakeDevice(newName, &device, permissions));
  824. }
  825.  
  826. /*
  827.  *----------------------------------------------------------------------
  828.  *
  829.  * Fs_MakeDirStub --
  830.  *
  831.  *    The Fs_MakeDir system call stub.
  832.  *
  833.  * Results:
  834.  *    Those of Fs_MakeDir.
  835.  *
  836.  * Side effects:
  837.  *    None.
  838.  *
  839.  *----------------------------------------------------------------------
  840.  */
  841.  
  842. ReturnStatus
  843. Fs_MakeDirStub(pathName, permissions)
  844.     char *pathName;
  845.     int permissions;
  846. {
  847.     int            pathNameLength;
  848.     char        newName[FS_MAX_PATH_NAME_LENGTH];
  849.  
  850.     /*
  851.      * Copy the name in from user space to the kernel stack.
  852.      */
  853.  
  854.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, pathName, newName,
  855.                &pathNameLength) != SUCCESS) {
  856.     return(SYS_ARG_NOACCESS);
  857.     }
  858.     if (pathNameLength == FS_MAX_PATH_NAME_LENGTH) {
  859.     return(FS_INVALID_ARG);
  860.     }
  861.  
  862.     return(Fs_MakeDir(newName, permissions));
  863. }
  864.  
  865. /*
  866.  *----------------------------------------------------------------------
  867.  *
  868.  * Fs_RemoveStub --
  869.  *
  870.  *    The stub for the Fs_Remove system call.
  871.  *
  872.  * Results:
  873.  *    Those of Fs_Remove.
  874.  *
  875.  * Side effects:
  876.  *    None.
  877.  *
  878.  *----------------------------------------------------------------------
  879.  */
  880.  
  881. ReturnStatus
  882. Fs_RemoveStub(pathName)
  883.     char *pathName;
  884. {
  885.     int            pathNameLength;
  886.     char        newName[FS_MAX_PATH_NAME_LENGTH];
  887.  
  888.     /*
  889.      * Copy the name in from user space to the kernel stack.
  890.      */
  891.  
  892.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, pathName, newName,
  893.                &pathNameLength) != SUCCESS) {
  894.     return(SYS_ARG_NOACCESS);
  895.     }
  896.     if (pathNameLength == FS_MAX_PATH_NAME_LENGTH) {
  897.     return(FS_INVALID_ARG);
  898.     }
  899.  
  900.     return(Fs_Remove(newName));
  901. }
  902.  
  903. /*
  904.  *----------------------------------------------------------------------
  905.  *
  906.  * Fs_RemoveDirStub --
  907.  *
  908.  *    The Fs_RemoveDir system call stub.
  909.  *
  910.  * Results:
  911.  *    The results of Fs_RemoveDir.
  912.  *
  913.  * Side effects:
  914.  *    None.
  915.  *
  916.  *----------------------------------------------------------------------
  917.  */
  918.  
  919. ReturnStatus
  920. Fs_RemoveDirStub(pathName)
  921.     char *pathName;
  922. {
  923.     int        pathNameLength;
  924.     char    newName[FS_MAX_PATH_NAME_LENGTH];
  925.  
  926.     /*
  927.      * Copy the name in from user space onto the kernel stack.
  928.      */
  929.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, pathName, newName,
  930.                &pathNameLength) != SUCCESS) {
  931.     return(SYS_ARG_NOACCESS);
  932.     }
  933.     if (pathNameLength == FS_MAX_PATH_NAME_LENGTH) {
  934.     return(FS_INVALID_ARG);
  935.     }
  936.  
  937.     return(Fs_RemoveDir(newName));
  938. }
  939.  
  940. /*
  941.  *----------------------------------------------------------------------
  942.  *
  943.  * Fs_ChangeDirStub --
  944.  *
  945.  *    The stub for the system call that changes the current directory.
  946.  *    The argument specifies a new current directory.  The argument
  947.  *    can be a relative path name.
  948.  *
  949.  * Results:
  950.  *    None.
  951.  *
  952.  * Side effects:
  953.  *    None.
  954.  *
  955.  *----------------------------------------------------------------------
  956.  */
  957.  
  958. ReturnStatus
  959. Fs_ChangeDirStub(pathName)
  960.     char *pathName;
  961. {
  962.     int        pathNameLength;
  963.     char    newName[FS_MAX_PATH_NAME_LENGTH];
  964.  
  965.     /*
  966.      * Copy the name in from user space onto the kernel stack.
  967.      */
  968.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, pathName, newName,
  969.                &pathNameLength) != SUCCESS) {
  970.     return(SYS_ARG_NOACCESS);
  971.     }
  972.     if (pathNameLength == FS_MAX_PATH_NAME_LENGTH) {
  973.     return(FS_INVALID_ARG);
  974.     }
  975.  
  976.     return(Fs_ChangeDir(newName));
  977. }
  978.  
  979. /*
  980.  *----------------------------------------------------------------------
  981.  *
  982.  * Fs_GetNewIDStub --
  983.  *
  984.  *    The stub for the system call that duplicates a stream ID.
  985.  *    See Fs_GetNewID.
  986.  *
  987.  * Results:
  988.  *    A return status.
  989.  *
  990.  * Side effects:
  991.  *    None.
  992.  *
  993.  *----------------------------------------------------------------------
  994.  */
  995. ReturnStatus
  996. Fs_GetNewIDStub(streamID, newStreamIDPtr)
  997.     int streamID;
  998.     int *newStreamIDPtr;
  999. {
  1000.     ReturnStatus     status;
  1001.     int         newStreamID;
  1002.  
  1003.     if (Vm_CopyIn(sizeof(int), (Address) newStreamIDPtr, 
  1004.           (Address) &newStreamID) != SUCCESS) {
  1005.     return(SYS_ARG_NOACCESS);
  1006.     }
  1007.     status = Fs_GetNewID(streamID, &newStreamID);
  1008.     if (status != SUCCESS) {
  1009.     return(status);
  1010.     }
  1011.  
  1012.     if (Vm_CopyOut(sizeof(int), (Address) &newStreamID, 
  1013.             (Address) newStreamIDPtr) != SUCCESS) {
  1014.     return(SYS_ARG_NOACCESS);
  1015.     } else {
  1016.     return(SUCCESS);
  1017.     }
  1018. }
  1019.  
  1020.  
  1021. /*
  1022.  *----------------------------------------------------------------------
  1023.  *
  1024.  * Fs_GetAttributesStub --
  1025.  *
  1026.  *    Stub for the Fs_GetAttributes system call.
  1027.  *
  1028.  * Results:
  1029.  *    The attributes for the named file.
  1030.  *
  1031.  * Side effects:
  1032.  *    *attrPtr is filled in with the attributes of the file.
  1033.  *
  1034.  *----------------------------------------------------------------------
  1035.  */
  1036. ReturnStatus
  1037. Fs_GetAttributesStub(pathName, fileOrLink, attrPtr)
  1038.     char *pathName;
  1039.     int fileOrLink;
  1040.     Fs_Attributes *attrPtr;
  1041. {
  1042.     ReturnStatus     status;
  1043.     Fs_Attributes    attributes;
  1044.     int            pathNameLength;
  1045.     char        newName[FS_MAX_PATH_NAME_LENGTH];
  1046.  
  1047.     /*
  1048.      * Copy the name in from user space onto the kernel stack.
  1049.      */
  1050.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, pathName, newName,
  1051.                &pathNameLength) != SUCCESS) {
  1052.     return(SYS_ARG_NOACCESS);
  1053.     }
  1054.     if (pathNameLength == FS_MAX_PATH_NAME_LENGTH) {
  1055.     return(FS_INVALID_ARG);
  1056.     }
  1057.  
  1058.     status = Fs_GetAttributes(newName, fileOrLink, &attributes);
  1059.     if (status != SUCCESS) {
  1060.     return(status);
  1061.     }
  1062.  
  1063.     if (Vm_CopyOut(sizeof(attributes), (Address) &attributes, 
  1064.            (Address) attrPtr) != SUCCESS) {
  1065.     return(SYS_ARG_NOACCESS);
  1066.     } else {
  1067.     return(SUCCESS);
  1068.     }
  1069. }
  1070.  
  1071.  
  1072. /*
  1073.  *----------------------------------------------------------------------
  1074.  *
  1075.  * Fs_CheckAccess --
  1076.  *
  1077.  *    Process the Fs_CheckAccess system all.
  1078.  *
  1079.  * Results:
  1080.  *    SYS_ARG_NOACCESS if pathname not accessible.
  1081.  *    FS_INVALID_ARG if pathname too long.
  1082.  *    Otherwise:
  1083.  *        SUCCESS if accessible.
  1084.  *        FS_NO_ACCESS if not accessible.
  1085.  *
  1086.  * Side effects:
  1087.  *    None.
  1088.  *
  1089.  *----------------------------------------------------------------------
  1090.  */
  1091. ReturnStatus
  1092. Fs_CheckAccess(pathName, perm, useRealID)
  1093.     char     *pathName;
  1094.     int        perm;
  1095.     Boolean    useRealID;
  1096. {
  1097.     ReturnStatus    status;
  1098.     Fs_Attributes    attributes;
  1099.     Proc_ControlBlock    *procPtr;
  1100.     int            pathNameLength;
  1101.     char        newName[FS_MAX_PATH_NAME_LENGTH];
  1102.     register int    bits;
  1103.  
  1104.     /*
  1105.      * Copy the name in from user space onto the kernel stack.
  1106.      */
  1107.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, pathName, newName,
  1108.                &pathNameLength) != SUCCESS) {
  1109.     return(SYS_ARG_NOACCESS);
  1110.     }
  1111.     if (pathNameLength == FS_MAX_PATH_NAME_LENGTH) {
  1112.     return(FS_INVALID_ARG);
  1113.     }
  1114.  
  1115.     procPtr = Proc_GetEffectiveProc();
  1116.  
  1117.     status = Fs_GetAttributes(newName, FS_ATTRIB_FILE, &attributes);
  1118.     if (status != SUCCESS) {
  1119.     return(status);
  1120.     } else if (perm == FS_EXISTS) {
  1121.     /*
  1122.      * Only checking for existence, not read or write access.
  1123.      */
  1124.     return(SUCCESS);
  1125.     } else if ((useRealID && (procPtr->userID == 0)) ||
  1126.         (!useRealID && (procPtr->effectiveUserID == 0))) {
  1127.     /*
  1128.      * Let the super-user do anything.
  1129.      */
  1130.     return(SUCCESS);
  1131.     }
  1132.     /*
  1133.      * Translate from FS_READ etc, into permission bits, ie. FS_WORLD_READ.
  1134.      * The world permissions are shifted left to the owner or group permissions
  1135.      * if the process's userID or one of its group IDs matches the file's.
  1136.      */
  1137.     bits = 0;
  1138.     if (perm & FS_READ) {
  1139.     bits |= FS_WORLD_READ;
  1140.     }
  1141.     if (perm & FS_WRITE) {
  1142.     bits |= FS_WORLD_WRITE;
  1143.     }
  1144.     if (perm & FS_EXECUTE) {
  1145.     bits |= FS_WORLD_EXEC;
  1146.     }
  1147.  
  1148.     if ((useRealID && attributes.uid == procPtr->userID) ||
  1149.         (!useRealID && attributes.uid == procPtr->effectiveUserID)) {
  1150.     bits <<= 6;
  1151.     } else {
  1152.     int    i;
  1153.     for (i = 0; i < procPtr->fsPtr->numGroupIDs; i++) {
  1154.         if (attributes.gid == procPtr->fsPtr->groupIDs[i]) {
  1155.         bits <<= 3;
  1156.         break;
  1157.         }
  1158.     }
  1159.     }
  1160.     if ((attributes.permissions & bits) == bits) {
  1161.     return (GEN_SUCCESS);
  1162.     } else {
  1163.     return (FS_NO_ACCESS);
  1164.     }
  1165. }
  1166.  
  1167.  
  1168. /*
  1169.  *----------------------------------------------------------------------
  1170.  *
  1171.  * Fs_GetAttributesIDStub --
  1172.  *
  1173.  *    Stub for the Fs_GetAttributesID system call.
  1174.  *
  1175.  * Results:
  1176.  *    Get the attributes for the file referred to by the specified
  1177.  *    descriptor.
  1178.  *
  1179.  * Side effects:
  1180.  *     *attrPtr is filled in with the attributes of the file.
  1181.  *
  1182.  *----------------------------------------------------------------------
  1183.  */
  1184. ReturnStatus
  1185. Fs_GetAttributesIDStub(streamID, attrPtr)
  1186.     int        streamID;    /* The user's index into its open file list */
  1187.     Fs_Attributes *attrPtr;    /* point to buffer to hold attributes */
  1188. {
  1189.     register    ReturnStatus     status;
  1190.     Fs_Stream            *streamPtr;
  1191.     Fs_Attributes         attributes;
  1192.  
  1193.     status = Fs_GetStreamPtr(Proc_GetEffectiveProc(), streamID, &streamPtr);
  1194.     if (status != SUCCESS) {
  1195.     return(status);
  1196.     }
  1197.     status = Fs_GetAttrStream(streamPtr, &attributes);
  1198.     if (status != SUCCESS) {
  1199.     return(status);
  1200.     }
  1201.  
  1202.     if (Vm_CopyOut(sizeof(attributes), (Address) &attributes, 
  1203.            (Address) attrPtr) != SUCCESS) {
  1204.     return(SYS_ARG_NOACCESS);
  1205.     } else {
  1206.     return(SUCCESS);
  1207.     }
  1208. }
  1209.  
  1210. /*
  1211.  *----------------------------------------------------------------------
  1212.  *
  1213.  * Fs_SetAttributesStub --
  1214.  *
  1215.  *    Stub for Fs_SetAttributes system call.  This is a general
  1216.  *    routine that sets ownership, access & modify times, permissions,
  1217.  *    and user-defined file type.  The calling process must own the file.    
  1218.  *
  1219.  * Results:
  1220.  *    A return status.
  1221.  *
  1222.  * Side effects:
  1223.  *    None here in this stub.
  1224.  *
  1225.  *----------------------------------------------------------------------
  1226.  */
  1227. ReturnStatus
  1228. Fs_SetAttributesStub(pathName, fileOrLink, attrPtr)
  1229.     char *pathName;
  1230.     int fileOrLink;
  1231.     Fs_Attributes *attrPtr;
  1232. {
  1233.     int                pathNameLength;
  1234.     Fs_Attributes        attr;
  1235.     char            newName[FS_MAX_PATH_NAME_LENGTH];
  1236.  
  1237.     if (Vm_CopyIn(sizeof(attr), (Address) attrPtr, 
  1238.           (Address) &attr) != SUCCESS) {
  1239.     return(SYS_ARG_NOACCESS);
  1240.     }
  1241.     /*
  1242.      * Copy the name in from user space onto the kernel stack.
  1243.      */
  1244.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, pathName, newName,
  1245.                &pathNameLength) != SUCCESS) {
  1246.     return(SYS_ARG_NOACCESS);
  1247.     }
  1248.     if (pathNameLength == FS_MAX_PATH_NAME_LENGTH) {
  1249.     return(FS_INVALID_ARG);
  1250.     }
  1251.  
  1252.     return(Fs_SetAttributes(newName, fileOrLink, &attr, FS_SET_ALL_ATTRS));
  1253. }
  1254.  
  1255. /*
  1256.  *----------------------------------------------------------------------
  1257.  *
  1258.  * Fs_SetAttrStub --
  1259.  *
  1260.  *    Stub for Fs_SetAttr system call.  Like the old Fs_SetAttributes
  1261.  *    but with an additional flag specifying exactly which attributes
  1262.  *    to update.
  1263.  *
  1264.  * Results:
  1265.  *    A return status.
  1266.  *
  1267.  * Side effects:
  1268.  *    None.
  1269.  *
  1270.  *----------------------------------------------------------------------
  1271.  */
  1272. ReturnStatus
  1273. Fs_SetAttrStub(pathName, fileOrLink, attrPtr, flags)
  1274.     char *pathName;        /* Name of file to manipulate */
  1275.     int fileOrLink;        /* Whether or not to follow symbolic links */
  1276.     Fs_Attributes *attrPtr;    /* New values for attributes */
  1277.     int flags;            /* What attributes to set */
  1278. {
  1279.     int                pathNameLength;
  1280.     Fs_Attributes        attr;
  1281.     char            newName[FS_MAX_PATH_NAME_LENGTH];
  1282.  
  1283.     if (Vm_CopyIn(sizeof(attr), (Address) attrPtr, 
  1284.           (Address) &attr) != SUCCESS) {
  1285.     return(SYS_ARG_NOACCESS);
  1286.     }
  1287.     /*
  1288.      * Copy the name in from user space onto the kernel stack.
  1289.      */
  1290.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, pathName, newName,
  1291.                &pathNameLength) != SUCCESS) {
  1292.     return(SYS_ARG_NOACCESS);
  1293.     }
  1294.     if (pathNameLength == FS_MAX_PATH_NAME_LENGTH) {
  1295.     return(FS_INVALID_ARG);
  1296.     }
  1297.  
  1298.     return(Fs_SetAttributes(newName, fileOrLink, &attr, flags));
  1299. }
  1300.  
  1301. /*
  1302.  *----------------------------------------------------------------------
  1303.  *
  1304.  * Fs_SetAttributesIDStub --
  1305.  *
  1306.  *    Stub for Fs_SetAttributesID system call.
  1307.  *
  1308.  * Results:
  1309.  *    A return status.
  1310.  *
  1311.  * Side effects:
  1312.  *    None.
  1313.  *
  1314.  *----------------------------------------------------------------------
  1315.  */
  1316. ReturnStatus
  1317. Fs_SetAttributesIDStub(streamID, attrPtr)
  1318.     int streamID;
  1319.     Fs_Attributes *attrPtr;
  1320. {
  1321.     register     ReturnStatus     status;
  1322.     Fs_Stream            *streamPtr;
  1323.     Fs_Attributes        attr;
  1324.     Fs_UserIDs            ids;
  1325.     Proc_ControlBlock        *procPtr;
  1326.  
  1327.     if (Vm_CopyIn(sizeof(attr), (Address) attrPtr, 
  1328.           (Address) &attr) != SUCCESS) {
  1329.     return(SYS_ARG_NOACCESS);
  1330.     }
  1331.  
  1332.     /*
  1333.      * Map from stream ID to file pointer and get the attributes.
  1334.      */
  1335.     procPtr = Proc_GetEffectiveProc();
  1336.     status = Fs_GetStreamPtr(procPtr, streamID, &streamPtr);
  1337.     if (status == SUCCESS) {
  1338.     Fs_SetIDs(procPtr, &ids);
  1339.     status = Fs_SetAttrStream(streamPtr, &attr, &ids, FS_SET_ALL_ATTRS);
  1340.     }
  1341.     return(status);
  1342. }
  1343.  
  1344. /*
  1345.  *----------------------------------------------------------------------
  1346.  *
  1347.  * Fs_SetAttrIDStub --
  1348.  *
  1349.  *    Stub for Fs_SetAttrID system call.  Like Fs_SetAttributesID
  1350.  *    but has a flag parameter that specifies what attrs to set.
  1351.  *
  1352.  * Results:
  1353.  *    A return status.
  1354.  *
  1355.  * Side effects:
  1356.  *    None.
  1357.  *
  1358.  *----------------------------------------------------------------------
  1359.  */
  1360. ReturnStatus
  1361. Fs_SetAttrIDStub(streamID, attrPtr, flags)
  1362.     int streamID;        /* References file to manipulate */
  1363.     Fs_Attributes *attrPtr;    /* New attributes for the file */
  1364.     int flags;            /* What attributes to set */
  1365. {
  1366.     register     ReturnStatus     status;
  1367.     Fs_Stream            *streamPtr;
  1368.     Fs_Attributes        attr;
  1369.     Fs_UserIDs            ids;
  1370.     Proc_ControlBlock        *procPtr;
  1371.  
  1372.     if (Vm_CopyIn(sizeof(attr), (Address) attrPtr, 
  1373.           (Address) &attr) != SUCCESS) {
  1374.     return(SYS_ARG_NOACCESS);
  1375.     }
  1376.  
  1377.     /*
  1378.      * Map from stream ID to file pointer and get the attributes.
  1379.      */
  1380.     procPtr = Proc_GetEffectiveProc();
  1381.     status = Fs_GetStreamPtr(procPtr, streamID, &streamPtr);
  1382.     if (status == SUCCESS) {
  1383.     Fs_SetIDs(procPtr, &ids);
  1384.     status = Fs_SetAttrStream(streamPtr, &attr, &ids, flags);
  1385.     }
  1386.     return(status);
  1387. }
  1388.  
  1389. /*
  1390.  *----------------------------------------------------------------------
  1391.  *
  1392.  * Fs_SetDefPermStub --
  1393.  *
  1394.  *    Set the default permissions on files created by this process.
  1395.  *    These defaults get inherited by child processes.
  1396.  *
  1397.  * Results:
  1398.  *    A return status.
  1399.  *
  1400.  * Side effects:
  1401.  *    Sets the default permissions mask in the filesystem related
  1402.  *    state kept in the proc table.
  1403.  *
  1404.  *----------------------------------------------------------------------
  1405.  */
  1406. ReturnStatus
  1407. Fs_SetDefPermStub(permissions, oldPermPtr)
  1408.     int permissions;    /*  A mask of 9 permission bits.  Three sets of 3
  1409.              * bits.  The first set is for the owner's permissions,
  1410.              * the second for the group's, and the last is for
  1411.              * everyone else.  The three bits indicate read,
  1412.              * write, and execute permissions, respectively.
  1413.              * A permission bit set in this mask ENABLES the
  1414.              * permission on created files. */
  1415.     int *oldPermPtr;    /* Output, the previous value of the permissions mask */
  1416. {
  1417.     register    Proc_ControlBlock    *procPtr;
  1418.     int                 oldPerm;
  1419.  
  1420.     procPtr = Proc_GetEffectiveProc();
  1421.     oldPerm = procPtr->fsPtr->filePermissions;
  1422.     procPtr->fsPtr->filePermissions = (unsigned int)(permissions & 0777);
  1423.     if (Proc_ByteCopy(FALSE, sizeof(int), (Address)&oldPerm, 
  1424.         (Address)oldPermPtr) != SUCCESS) {
  1425.     return(SYS_ARG_NOACCESS);
  1426.     } else {
  1427.     return(SUCCESS);
  1428.     }
  1429. }
  1430.  
  1431. /*
  1432.  *----------------------------------------------------------------------
  1433.  *
  1434.  * Fs_HardLinkStub --
  1435.  *
  1436.  *    Stub for the Fs_HardLink system call.
  1437.  *
  1438.  * Results:
  1439.  *    A return status.
  1440.  *
  1441.  * Side effects:
  1442.  *    None.
  1443.  *
  1444.  *----------------------------------------------------------------------
  1445.  */
  1446. ReturnStatus
  1447. Fs_HardLinkStub(fileName, linkName)
  1448.     char *fileName;    /* Name of the existing file */
  1449.     char *linkName;    /* New name to link to the existing file */
  1450. {
  1451.     ReturnStatus     status = SUCCESS;
  1452.     int            fileNameLength;
  1453.     int            linkNameLength;
  1454.     char        newFileName[FS_MAX_PATH_NAME_LENGTH];
  1455.     char        *newLinkName;
  1456.  
  1457.     /*
  1458.      * Copy the filename in from user space onto the kernel stack.
  1459.      */
  1460.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, fileName, newFileName,
  1461.                &fileNameLength) != SUCCESS) {
  1462.     return(SYS_ARG_NOACCESS);
  1463.     }
  1464.     if (fileNameLength == FS_MAX_PATH_NAME_LENGTH) {
  1465.     return(FS_INVALID_ARG);
  1466.     }
  1467.  
  1468.     /*
  1469.      * Maybe I could put the link name onto the stack as well but I am 
  1470.      * allocing it here because I'm not sure if the stack is big enough.
  1471.      * Should just make the stack bigger I suppose ...
  1472.      */
  1473.     newLinkName = (char  *) malloc(FS_MAX_PATH_NAME_LENGTH);
  1474.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, linkName, newLinkName,
  1475.                &linkNameLength) == SUCCESS) {
  1476.     if (linkNameLength == FS_MAX_PATH_NAME_LENGTH) {
  1477.         status = FS_INVALID_ARG;
  1478.     } else {
  1479.         status = Fs_HardLink(newFileName, newLinkName);
  1480.     }
  1481.     } else {
  1482.     status = SYS_ARG_NOACCESS;
  1483.     }
  1484.  
  1485.     free((Address) newLinkName);
  1486.  
  1487.     return(status);
  1488. }
  1489.  
  1490.  
  1491. /*
  1492.  *----------------------------------------------------------------------
  1493.  *
  1494.  * Fs_RenameStub --
  1495.  *
  1496.  *    Stub for Fs_Rename system call.
  1497.  *
  1498.  * Results:
  1499.  *    A return status.
  1500.  *
  1501.  * Side effects:
  1502.  *    None.
  1503.  *
  1504.  *----------------------------------------------------------------------
  1505.  */
  1506. ReturnStatus
  1507. Fs_RenameStub(pathName, newName)
  1508.     char *pathName;
  1509.     char *newName;
  1510. {
  1511.     ReturnStatus    status;
  1512.     int            pathNameLength;
  1513.     int            newNameLength;
  1514.     char        newPathName[FS_MAX_PATH_NAME_LENGTH];
  1515.     char        *newNewName;
  1516.  
  1517.     /*
  1518.      * Copy the name in from user space onto the kernel stack.
  1519.      */
  1520.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, pathName, newPathName,
  1521.                &pathNameLength) != SUCCESS) {
  1522.     return(SYS_ARG_NOACCESS);
  1523.     }
  1524.     if (pathNameLength == FS_MAX_PATH_NAME_LENGTH) {
  1525.     return(FS_INVALID_ARG);
  1526.     }
  1527.  
  1528.     /*
  1529.      * Maybe I could put the new name onto the stack as well but I am 
  1530.      * allocing it here because I'm not sure if the stack is big enough.
  1531.      * Should just make the stack bigger I suppose ...
  1532.      */
  1533.     newNewName = (char  *) malloc(FS_MAX_PATH_NAME_LENGTH);
  1534.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, newName, newNewName,
  1535.                &newNameLength) == SUCCESS) {
  1536.     if (newNameLength == FS_MAX_PATH_NAME_LENGTH) {
  1537.         status = FS_INVALID_ARG;
  1538.     } else {
  1539.         status = Fs_Rename(newPathName, newNewName);
  1540.     }
  1541.     } else {
  1542.     status = SYS_ARG_NOACCESS;
  1543.     }
  1544.  
  1545.     free((Address) newNewName);
  1546.  
  1547.     return(status);
  1548. }
  1549.  
  1550.  
  1551. /*
  1552.  *----------------------------------------------------------------------
  1553.  *
  1554.  * Fs_SymLinkStub --
  1555.  *
  1556.  *    Stub for Fs_SymLink system call.
  1557.  *
  1558.  * Results:
  1559.  *    None.
  1560.  *
  1561.  * Side effects:
  1562.  *    None.
  1563.  *
  1564.  *----------------------------------------------------------------------
  1565.  */
  1566. ReturnStatus
  1567. Fs_SymLinkStub(targetName, linkName, remoteFlag)
  1568.     char *targetName;
  1569.     char *linkName;
  1570.     Boolean remoteFlag;
  1571. {
  1572.     ReturnStatus    status;
  1573.     int            targetNameLength;
  1574.     int            linkNameLength;
  1575.     char        newTargetName[FS_MAX_PATH_NAME_LENGTH];
  1576.     char        *newLinkName;
  1577.  
  1578.     /*
  1579.      * Copy the name in from user space onto the kernel stack.
  1580.      */
  1581.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, targetName, newTargetName,
  1582.                &targetNameLength) != SUCCESS) {
  1583.     return(SYS_ARG_NOACCESS);
  1584.     }
  1585.     if (targetNameLength == FS_MAX_PATH_NAME_LENGTH) {
  1586.     return(FS_INVALID_ARG);
  1587.     }
  1588.  
  1589.     /*
  1590.      * Maybe I could put the new name onto the stack as well but I am 
  1591.      * allocing it here because I'm not sure if the stack is big enough.
  1592.      * Should just make the stack bigger I suppose ...
  1593.      */
  1594.     newLinkName = (char  *) malloc(FS_MAX_PATH_NAME_LENGTH);
  1595.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, linkName, newLinkName,
  1596.                &linkNameLength) == SUCCESS) {
  1597.     if (linkNameLength == FS_MAX_PATH_NAME_LENGTH) {
  1598.         status = FS_INVALID_ARG;
  1599.     } else {
  1600.         status = Fs_SymLink(newTargetName, newLinkName, remoteFlag);
  1601.     }
  1602.     } else {
  1603.     status = SYS_ARG_NOACCESS;
  1604.     }
  1605.     free((Address) newLinkName);
  1606.  
  1607.     return(status);
  1608. }
  1609.  
  1610.  
  1611. /*
  1612.  *----------------------------------------------------------------------
  1613.  *
  1614.  * Fs_ReadLinkStub --
  1615.  *
  1616.  *    Stub for Fs_ReadLink system call.  The named file should be a
  1617.  *    remote link or a symbolic link file.  It is opened and its
  1618.  *    contents (another file's name) are read and stored in the buffer.
  1619.  *
  1620.  * Results:
  1621.  *    A return code from the open and read.
  1622.  *
  1623.  * Side effects:
  1624.  *    Fills in the buffer with contents of the link file, and
  1625.  *    returns the amount of data stored there in *linkSizePtr.
  1626.  *
  1627.  *----------------------------------------------------------------------
  1628.  */
  1629. ReturnStatus
  1630. Fs_ReadLinkStub(linkName, bufSize, buffer, linkSizePtr)
  1631.     char *linkName;        /* Name of the link file */
  1632.     int bufSize;        /* Size of the user's buffer */
  1633.     char *buffer;        /* The buffer to hold the link's value */
  1634.     int *linkSizePtr;        /* Return, the amount of data in buffer */
  1635. {
  1636.     ReturnStatus    status;
  1637.     Fs_Stream        *streamPtr;
  1638.     int            linkNameLength;
  1639.     char        newLinkName[FS_MAX_PATH_NAME_LENGTH];
  1640.  
  1641.     /*
  1642.      * Copy the name in from user space onto the kernel stack.
  1643.      */
  1644.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, linkName, newLinkName,
  1645.                &linkNameLength) != SUCCESS) {
  1646.     return(SYS_ARG_NOACCESS);
  1647.     }
  1648.     if (linkNameLength == FS_MAX_PATH_NAME_LENGTH) {
  1649.     return(FS_INVALID_ARG);
  1650.     }
  1651.  
  1652.     status = Fs_Open(newLinkName, FS_READ | FS_USER,
  1653.              FS_SYMBOLIC_LINK|FS_REMOTE_LINK, 0, &streamPtr);
  1654.     if (status == SUCCESS) {
  1655.     status = Fs_Read(streamPtr, buffer, 0, &bufSize);
  1656.     if (status == SUCCESS) {
  1657.         /*
  1658.          * Sprite's link count includes the terminating null character
  1659.          * in the character count return while Unix doesn't.  Make our
  1660.          * count backward-compatible with Unix.
  1661.          */
  1662.          status = Proc_ByteCopy(TRUE, sizeof(int), (Address) &bufSize,
  1663.             (Address) &linkNameLength);
  1664.         if (status == SUCCESS) {
  1665.         if (linkNameLength >= FS_MAX_PATH_NAME_LENGTH) {
  1666.             status = FS_INVALID_ARG;
  1667.         } else {
  1668.             status = Proc_ByteCopy(TRUE, linkNameLength,
  1669.                 (Address) buffer, (Address) newLinkName);
  1670.             if (status == SUCCESS &&
  1671.                 newLinkName[linkNameLength-1] == '\0') {
  1672.             linkNameLength--;
  1673.             status = Proc_ByteCopy(FALSE, sizeof(int),
  1674.                 (Address) &linkNameLength, (Address) &bufSize);
  1675.             }
  1676.         }
  1677.         }
  1678.         status = Proc_ByteCopy(FALSE, sizeof(int), (Address)&linkNameLength,
  1679.                    (Address)linkSizePtr);
  1680.     }
  1681.     (void)Fs_Close(streamPtr);
  1682.     }
  1683.     return(status);
  1684. }
  1685.  
  1686. /*
  1687.  *----------------------------------------------------------------------
  1688.  *
  1689.  * Fs_IOControlStub --
  1690.  *
  1691.  *    Stub for the Fs_IOControl system call.  IOControl commands
  1692.  *    that affect Fs_Stream objects are done here.  The rest of
  1693.  *    the commands are passed down to the stream type specific
  1694.  *    IOControl procedures.
  1695.  *
  1696.  * Results:
  1697.  *    A return status.  The output buffer is modified with results
  1698.  *    for the command.  The format of the various results is explained
  1699.  *    in user/fs.h for generic operations, and in dev/ *.h for
  1700.  *    device specific operations.
  1701.  *
  1702.  * Side effects:
  1703.  *    Depends on the command.
  1704.  *
  1705.  *----------------------------------------------------------------------
  1706.  */
  1707.  
  1708. ReturnStatus
  1709. Fs_IOControlStub(streamID, command, inBufSize, inBuffer,
  1710.                outBufSize, outBuffer)
  1711.     int     streamID;    /* User's handle on the stream */
  1712.     int     command;    /* IOControl command */
  1713.     int     inBufSize;    /* Size of inBuffer */
  1714.     Address     inBuffer;    /* Command specific input parameters */
  1715.     int     outBufSize;    /* Size of outBuffer */
  1716.     Address     outBuffer;    /* Command specific output parameters */
  1717. {
  1718.     Proc_ControlBlock *procPtr;
  1719.     Fs_ProcessState *fsPtr;
  1720.     Fs_Stream      *streamPtr;
  1721.     register ReturnStatus status = SUCCESS;
  1722.     Address    localInBuffer = (Address)NIL;
  1723.     Address    localOutBuffer = (Address)NIL;
  1724.     Fs_IOCParam ioctl;
  1725.     Fs_IOReply reply;
  1726.  
  1727.     /*
  1728.      * Get a stream pointer.
  1729.      */
  1730.     procPtr = Proc_GetEffectiveProc();
  1731.     status = Fs_GetStreamPtr(procPtr, streamID, &streamPtr);
  1732.     if (status != SUCCESS) {
  1733.     return(status);
  1734.     }
  1735.  
  1736.     if (!Fsutil_HandleValid(streamPtr->ioHandlePtr)) {
  1737.     return(FS_STALE_HANDLE);
  1738.     }
  1739.  
  1740.     ioctl.command = command;
  1741.     ioctl.format = mach_Format;
  1742.     ioctl.procID = procPtr->processID;
  1743.     ioctl.familyID = procPtr->familyID;
  1744.     ioctl.uid = procPtr->effectiveUserID;
  1745.  
  1746.     /*
  1747.      * Fast path for non-generic I/O controls to pseudo-devices.
  1748.      * We don't copy in/out the user's parameter blocks because the
  1749.      * pseudo-device code does direct cross-address-space copy later.
  1750.      * We also skip the check against large parameter blocks so arbitrary
  1751.      * amounts of data can be fed to and from a pseudo-device.
  1752.      */
  1753.     if ((streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM) &&
  1754.     (command > IOC_GENERIC_LIMIT)) {
  1755.     ioctl.inBufSize = inBufSize;
  1756.     ioctl.inBuffer = inBuffer;
  1757.     ioctl.outBufSize = outBufSize;  
  1758.     ioctl.outBuffer = outBuffer;
  1759.     ioctl.flags = FS_USER_IN|FS_USER_OUT;
  1760.     return(Fs_IOControl(streamPtr, &ioctl, &reply));
  1761.     }
  1762.  
  1763.     if (inBufSize > IOC_MAX_BYTES || outBufSize > IOC_MAX_BYTES) {
  1764.     return(SYS_INVALID_ARG);
  1765.     }
  1766.     ioctl.flags = 0;    /* We'll copy buffer's into/out of the kernel */
  1767.  
  1768.     /*
  1769.      * The input parameters are copied into kernel
  1770.      * space, and the results are copied back out so that the
  1771.      * lower level routines don't have to worry about it.
  1772.      */
  1773.     if ((outBufSize > 0) && (outBuffer != (Address)0) &&
  1774.                 (outBuffer != (Address)NIL)){
  1775.     ioctl.outBuffer = localOutBuffer = (Address) malloc(outBufSize);
  1776.     ioctl.outBufSize = outBufSize;
  1777.     } else {
  1778.     ioctl.outBuffer = (Address)NIL;
  1779.     ioctl.outBufSize = outBufSize = 0;
  1780.     }
  1781.     if ((inBufSize > 0) && (inBuffer != (Address)0) &&
  1782.                (inBuffer != (Address)NIL)) {
  1783. #ifdef SOSP91
  1784.     /*
  1785.      * Allocate space after the arguments on an IOC_REPOSITION for the
  1786.      * current offset.
  1787.      */
  1788.     ioctl.inBuffer  = localInBuffer = (Address) 
  1789.                 malloc(inBufSize + 3 * sizeof(int));
  1790. #else
  1791.     ioctl.inBuffer  = localInBuffer = (Address) malloc(inBufSize);
  1792. #endif
  1793.     ioctl.inBufSize = inBufSize;
  1794.     } else {
  1795.     ioctl.inBuffer = (Address)NIL;
  1796.     ioctl.inBufSize = 0;
  1797.     }
  1798.  
  1799.     if (ioctl.inBufSize &&
  1800.     Vm_CopyIn(ioctl.inBufSize, inBuffer, ioctl.inBuffer) != SUCCESS) {
  1801.     status = SYS_ARG_NOACCESS;
  1802.     } else {
  1803.     status = Fs_IOControl(streamPtr, &ioctl, &reply);
  1804.     if (status == SUCCESS) {
  1805.         /*
  1806.          * Post process the set/get flags stuff because the close-on-exec
  1807.          * flag is not kept down at the stream level, but up along
  1808.          * with the streamID.
  1809.          */
  1810.         fsPtr = procPtr->fsPtr;
  1811.         switch(command) {
  1812.         case IOC_GET_FLAGS: {
  1813.             if (fsPtr->streamFlags[streamID] & FS_CLOSE_ON_EXEC) {
  1814.             *(int *)ioctl.outBuffer |= IOC_CLOSE_ON_EXEC;
  1815.             }
  1816.             break;
  1817.         }
  1818.         case IOC_SET_BITS:
  1819.         case IOC_SET_FLAGS: {
  1820.             int flags;
  1821.             flags = *(int *)ioctl.inBuffer;
  1822.  
  1823.             if (flags & IOC_CLOSE_ON_EXEC) {
  1824.             fsPtr->streamFlags[streamID] |= FS_CLOSE_ON_EXEC;
  1825.             } else if (command == IOC_SET_FLAGS) {
  1826.             fsPtr->streamFlags[streamID] &= ~FS_CLOSE_ON_EXEC;
  1827.             }
  1828.             break;
  1829.         }
  1830.         case IOC_CLEAR_BITS:{
  1831.             int flags;
  1832.             flags = *(int *)ioctl.inBuffer;
  1833.             if (flags & IOC_CLOSE_ON_EXEC) {
  1834.             fsPtr->streamFlags[streamID] &= ~FS_CLOSE_ON_EXEC;
  1835.             }
  1836.             break;
  1837.         }
  1838.         }
  1839.         if (outBufSize) {
  1840.         status = Vm_CopyOut(reply.length, ioctl.outBuffer,
  1841.                     outBuffer);
  1842.         }
  1843.     }
  1844.     }
  1845.     if (localInBuffer != (Address)NIL) {
  1846.     free(localInBuffer);
  1847.     }
  1848.     if (localOutBuffer != (Address)NIL) {
  1849.     free(localOutBuffer);
  1850.     }
  1851.     return(status);
  1852. }
  1853.  
  1854.  
  1855. /*
  1856.  *----------------------------------------------------------------------
  1857.  *
  1858.  * Fs_CreatePipeStub --
  1859.  *
  1860.  *      This is the stub for the Fsio_CreatePipe system call.  This routine sets
  1861.  *      up stream IDs for the two Fs_Stream objects returned by (the internal)
  1862.  *      Fsio_CreatePipe: one for reading the pipe and one for writing to it.
  1863.  *
  1864.  * Results:
  1865.  *    A retrun status or SUCCESS if successful.
  1866.  *
  1867.  * Side effects:
  1868.  *    The two arguments are out parameters and get filled in with a
  1869.  *    stream id.  Also, opening a pipe sets up state until both ends are 
  1870.  *    closed with Fs_Close system calls.
  1871.  *
  1872.  *----------------------------------------------------------------------
  1873.  */
  1874. ReturnStatus
  1875. Fs_CreatePipeStub(inStreamIDPtr, outStreamIDPtr)
  1876.     int *inStreamIDPtr;        /* Handle that the user can use to read the
  1877.                  * pipe. */
  1878.     int *outStreamIDPtr;    /* Handle that the user can use to write the
  1879.                  * pipe. */
  1880. {
  1881.     register ReturnStatus    status;
  1882.     Fs_Stream            *inStreamPtr;
  1883.     int                 inStreamID;
  1884.     Fs_Stream            *outStreamPtr;
  1885.     int                outStreamID;
  1886.  
  1887.     /*
  1888.      * Call the internal routine to create the pipe.
  1889.      */
  1890.     status = Fsio_CreatePipe(&inStreamPtr, &outStreamPtr);
  1891.     if (status != SUCCESS) {
  1892.     return(status);
  1893.     }
  1894.     inStreamPtr->flags |= FS_USER;
  1895.     outStreamPtr->flags |= FS_USER;
  1896.  
  1897.     /*
  1898.      * Get stream ids for the two streams.
  1899.      */
  1900.  
  1901.     status = Fs_GetStreamID(inStreamPtr, &inStreamID);
  1902.     if (status != SUCCESS) {
  1903.     (void) Fs_Close(inStreamPtr);
  1904.     (void) Fs_Close(outStreamPtr);
  1905.     return(status);
  1906.     }
  1907.     status = Fs_GetStreamID(outStreamPtr, &outStreamID);
  1908.     if (status != SUCCESS) {
  1909.     Fs_ClearStreamID(inStreamID, (Proc_ControlBlock *)NIL);
  1910.     (void) Fs_Close(inStreamPtr);
  1911.     (void) Fs_Close(outStreamPtr);
  1912.     return(status);
  1913.     }
  1914.  
  1915.     /*
  1916.      * Copy out the stream ids to the user.
  1917.      */
  1918.  
  1919.     if (Vm_CopyOut(sizeof(int), (Address) &inStreamID, 
  1920.            (Address) inStreamIDPtr) == SUCCESS &&
  1921.     Vm_CopyOut(sizeof(int), (Address) &outStreamID, 
  1922.            (Address) outStreamIDPtr) == SUCCESS) {
  1923.     return(SUCCESS);
  1924.     }
  1925.  
  1926.     /*
  1927.      * If couldn't copy out then clean up state and return an error.
  1928.      */
  1929.  
  1930.     Fs_ClearStreamID(inStreamID, (Proc_ControlBlock *)NIL);
  1931.     Fs_ClearStreamID(outStreamID, (Proc_ControlBlock *)NIL);
  1932.     (void) Fs_Close(inStreamPtr);
  1933.     (void) Fs_Close(outStreamPtr);
  1934.  
  1935.     return(SYS_ARG_NOACCESS);
  1936. }
  1937.  
  1938.